package com.mjw.tender.controller;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.mjw.tender.api.TbRoleService;
import com.mjw.tender.api.TbUserService;
import com.mjw.tender.domain.TbRole;
import com.mjw.tender.domain.TbUser;
import com.mjw.tender.dto.LoginParam;
import com.mjw.tender.dto.ResponseResult;
import com.mjw.tender.util.TokenUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api")
public class LoginController {

    @Resource
    UserDetailsService userDetailsService;

    @Resource
    TbUserService tbUserService;

    @Reference(version = "1.0.0")
    TbRoleService tbRoleService;

    @Autowired
    PasswordEncoder passwordEncoder;

    @Value("${tender.oauth2.grant_type}")
    public String oauth2GrantType;

    @Value("${tender.oauth2.client_id}")
    public String oauth2ClientId;

    @Value("${tender.oauth2.client_secret}")
    public String oauth2ClientSecret;

    @Value("${tender.oauth2.url}")
    public String oauth2Url;

    @Autowired
    TokenStore tokenStore;

    /**
     * 根据用户名密码获取token
     * @param loginParam
     * @return
     */
    @RequestMapping("/login")
//    @SentinelResource(value = "test",fallback = "testFallBack",fallbackClass = LoginControllerFallBack.class)
    public ResponseResult getToken(@RequestBody LoginParam loginParam){
        UserDetails userDetails  = userDetailsService.loadUserByUsername(loginParam.getUsername());
        if (userDetails == null){
            return new ResponseResult(ResponseResult.CodeStatus.FAIL,"用户不存在");
        }
        if(!passwordEncoder.matches(loginParam.getPassword(),userDetails.getPassword())){
            return  new ResponseResult(ResponseResult.CodeStatus.FAIL,"密码错误");
        }

        // 封装密码模式下获取token所需要的参数
        Map params = new HashMap();
        params.put("username",loginParam.getUsername());
        params.put("password",loginParam.getPassword());
        params.put("grant_type",oauth2GrantType);
        params.put("client_id",oauth2ClientId);
        params.put("client_secret",oauth2ClientSecret);

        String result  =  HttpUtil.post(oauth2Url,params);
        JSONObject data = JSONUtil.parseObj(result);
        return new ResponseResult(ResponseResult.CodeStatus.OK,data);
    }

    /**
     * 注销
     *
     */
    @PreAuthorize("hasAuthority('User')")
    @PostMapping(value = "/logout")
    public ResponseResult logout(HttpServletRequest request) {
        String token = TokenUtil.getTokenFromReq(request);
        // 删除 token 以注销
        OAuth2AccessToken oAuth2AccessToken = tokenStore.readAccessToken(token);
        tokenStore.removeAccessToken(oAuth2AccessToken);
        return new ResponseResult(ResponseResult.CodeStatus.OK,"退出登录");
    }


    /**
     * 获取用户信息，姓名和头像
     * @return
     */
//    @PreAuthorize("hasAuthority('System')")
    @GetMapping("/info")
    public ResponseResult getUserInfo(){
        // 获取认证信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Map data = new HashMap();
        TbUser tbUser = tbUserService.get(authentication.getName());
        tbUser.setPassword("");//密码不外传
        List<TbRole> tbRoles = tbRoleService.getRolesByUserId(tbUser.getId());
        //有需要可以把权限也查出来 TODO
        data.put("name",authentication.getName());
        data.put("roles",tbRoles);
        data.put("user",tbUser);
        return new ResponseResult(ResponseResult.CodeStatus.OK,data);
    }

    @PostMapping("/user")
//    @SentinelResource(value = "addUserReturnId",fallback = "addUserReturnIdFallBack",fallbackClass = LoginControllerFallBack.class)
    public ResponseResult<Long> addUserReturnId(@RequestBody TbUser tbUser){
         Long id = tbUserService.addReturnId(tbUser);
        return new ResponseResult<Long>(ResponseResult.CodeStatus.OK,id);
    }
}
